package com.atguigu.spzx.manager.service.Impl;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.core.util.IdUtil;
import com.atguigu.spyx.model.common.ResultCodeEnum;
import com.atguigu.spyx.model.common.com.atguigu.spyx.model.entity.sys.SysUser;
import com.atguigu.spyx.model.dto.system.LoginDto;
import com.atguigu.spyx.model.dto.system.SysUserDto;
import com.atguigu.spyx.model.exception.SpzxException;
import com.atguigu.spyx.model.vo.system.LoginVo;
import com.atguigu.spyx.model.vo.system.ValidateCodeVo;
import com.atguigu.spzx.manager.mapper.SysUserMapper;
import com.atguigu.spzx.manager.service.SysUserService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import jakarta.annotation.Resource;
import lombok.val;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author LT
 * @create 2023-10-31-19:43
 */
@Service
public class SysUserServiceImpl implements SysUserService {

    @Resource
    SysUserMapper sysUserMapper;

    @Resource
    RedisTemplate redisTemplate;

    @Override
    public SysUser getUserInfo(String token) {
        Object sysUser = redisTemplate.opsForValue().get("sys:user:login" + token);
        if (sysUser == null) {
            throw new SpzxException(ResultCodeEnum.LOGIN_EXPIRE_ERROR , null);
        }
        return (SysUser) sysUser;
    }

    @Override
    public LoginVo login(LoginDto loginDto) {
        String userName = loginDto.getUserName();
        String password = loginDto.getPassword();
        String code = loginDto.getCode();
        String codeKey = loginDto.getCodeKey();

        if (StringUtils.isEmpty(userName)||StringUtils.isEmpty(password)){
            throw new SpzxException(ResultCodeEnum.LOGIN_ERROR,null);
        }
        //1、根据账号查询管理员用户信息
        SysUser sysUser =sysUserMapper.findSysUserByUserName(userName);
        //2、如果查询失败 返回账号错误
        if (sysUser==null){
            throw new SpzxException(201,"账号错误",null);
        }
        //3、使用传入的密码 加密后和查询到的管理员用户的密码比较
        //数据库中密码使用了spring提供的MD5加密工具加密
        String inputPwd = DigestUtils.md5DigestAsHex(password.getBytes());
        System.out.println(inputPwd);
        //4、如果密码错误 返回密码错误
        if (!StringUtils.equals(sysUser.getPassword(),inputPwd)){
            throw new SpzxException(201,"密码错误",null);
        }
        //验证码校验
        Object codeObj = redisTemplate.opsForValue().get("sys:user:login"+codeKey);
        if (codeObj==null||!code.equals(codeObj.toString())){
            throw new SpzxException(ResultCodeEnum.LOGIN_CODE_ERROR,null);
        }
        //5、生成token ：token映射 查询到的管理员用户对象
        //hutool工具包可以通过工具类生成19位长度的唯一的按时间顺序递增的id
        String token = IdUtil.createSnowflake(1,1).nextIdStr();
        //存到redis中保持登录状态: 设置7天的过期时间
        sysUser.setPassword(null);
        //redisTemplate存储自定义类型的对象时 必须实现序列化接口
        // 通过图形化工具 查看redisTemplate序列化的对象时 数据不可读
        redisTemplate.opsForValue().set("sys:user:login"+token,sysUser,7, TimeUnit.DAYS);
        //给redisTemplate设置键(使用字符串直接存) 和 值(转为json直接存) 的序列化器工具
        //6、创建LoginVo携带前端需要的参数返回
        LoginVo loginVo = new LoginVo();
        loginVo.setToken(token);
        loginVo.setRefresh_token("1");
        return loginVo;
    }

    @Override
    public ValidateCodeVo genValidateCodeImg() {
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(120,50,4,20);
        String image = lineCaptcha.getImageBase64();
        String code = lineCaptcha.getCode();
        String token = IdUtil.createSnowflake(1,1).nextIdStr();
        redisTemplate.opsForValue().set("sys:user:login"+token,code,10,TimeUnit.MINUTES);

        ValidateCodeVo validateCodeVo = new ValidateCodeVo();
        validateCodeVo.setCodeImg(image);
        validateCodeVo.setCodeKey(token);

        return validateCodeVo;
    }

    @Override
    public void Logout(String token) {
        redisTemplate.delete("sys:user:login"+token);
    }

    @Override
    public PageInfo<SysUser> getUserPage(Integer pageNum, Integer pageSize, SysUserDto sysUserDto) {
        PageHelper.startPage(pageNum,pageSize);

       List<SysUser> users = sysUserMapper.getUserPage(sysUserDto);

        PageInfo<SysUser> pageInfo = new PageInfo<>(users);

        return pageInfo;
    }

    @Override
    public void deleteById(Integer id) {
        sysUserMapper.deleteById(id);
    }

    @Override
    public SysUser getById(Integer id) {
        return sysUserMapper.getById(id);
    }

    @Override
    public void updateById(SysUser sysUser) {
        sysUserMapper.updateById(sysUser);
    }

    @Override
    public void saveUser(SysUser sysUser) {
        sysUserMapper.saveUser(sysUser);
    }
}
